/**
 * @author Jason Pratt
 */

package edu.cmu.cs.stage3.alice.authoringtool;

import java.awt.Component;

import edu.cmu.cs.stage3.alice.authoringtool.datatransfer.CallToUserDefinedQuestionPrototypeReferenceTransferable;
import edu.cmu.cs.stage3.alice.authoringtool.datatransfer.CallToUserDefinedResponsePrototypeReferenceTransferable;
import edu.cmu.cs.stage3.alice.authoringtool.datatransfer.ElementPrototypeReferenceTransferable;
import edu.cmu.cs.stage3.alice.authoringtool.datatransfer.ElementReferenceTransferable;
import edu.cmu.cs.stage3.alice.authoringtool.datatransfer.PropertyReferenceTransferable;
import edu.cmu.cs.stage3.alice.authoringtool.editors.compositeeditor.MainCompositeElementPanel;
import edu.cmu.cs.stage3.alice.authoringtool.py.AliceStyle;
import edu.cmu.cs.stage3.alice.authoringtool.viewcontroller.CollectionPropertyViewController;
import edu.cmu.cs.stage3.alice.authoringtool.viewcontroller.PropertyViewController;
import edu.cmu.cs.stage3.alice.core.reference.PropertyReference;
import edu.cmu.cs.stage3.resourceBundle.I18n;
import edu.cmu.cs.stage3.util.Criterion;
import edu.cmu.cs.stage3.util.Enumerable;
import edu.cmu.cs.stage3.util.HowMuch;
import edu.cmu.cs.stage3.util.StringObjectPair;

public class AuthoringToolResources {

  public final static long startTime = System.currentTimeMillis();
  public final static String QUESTION_STRING = "function";
  public static Criterion characterCriterion = new Criterion() {
    public boolean accept (Object o) {
      return o instanceof edu.cmu.cs.stage3.alice.core.Sandbox;
      }
    };

  public static class Resources implements java.io.Serializable {
    public java.util.Vector questionStructure; // all available functions
    public java.util.HashMap nameMap = new java.util.HashMap();
    public java.util.HashMap htmlNameMap = new java.util.HashMap();
    public java.util.HashMap formatMap = new java.util.HashMap();
    public java.util.Vector defaultPropertyValuesStructure;
    public java.util.HashMap colorMap = new java.util.HashMap();
    public java.text.DecimalFormat decimalFormatter = new java.text.DecimalFormat( "#0.##" );
    public java.util.HashMap stringImageMap = new java.util.HashMap();
    public java.util.HashMap stringIconMap = new java.util.HashMap();
    public java.util.HashMap disabledIconMap = new java.util.HashMap();
    public java.util.HashMap flavorMap = new java.util.HashMap();
    public java.util.HashMap keyCodesToStrings = new java.util.HashMap();
    }

  protected static Resources resources;
  protected static java.io.File resourcesCacheFile;

  static {
    loadResourcesPy();
    }

  // Chamado de: at edu.cmu.cs.stage3.alice.authoringtool.AuthoringToolResources.safeIsDataFlavorSupported(AuthoringToolResources.java:75)
  //             at edu.cmu.cs.stage3.alice.authoringtool.editors.compositeeditor.CompositeComponentElementPanel.dragEnter(CompositeComponentElementPanel.java:445)
  //- private static int conta=0;
  public static boolean safeIsDataFlavorSupported (java.awt.dnd.DropTargetDragEvent dtde, java.awt.datatransfer.DataFlavor flavor) {
  //- if (conta==1) {
  //-   System.out.println("src/edu/cmu/cs/stage3/alice/authoringtool/AuthoringToolResources.java: safeIsDataFlavorSupported: "+flavor); // +dtde+" , "
  //-   try{String str=""; System.out.println(str.charAt(3));}catch(Exception e) {e.printStackTrace();}
  //- }
  //-conta++;
    try {
      boolean toReturn = dtde.isDataFlavorSupported(flavor);
      return toReturn;
    } catch (Throwable t) {
      return false;
    }
  }

  public static java.awt.datatransfer.DataFlavor[] safeGetCurrentDataFlavors(java.awt.dnd.DropTargetDropEvent dtde){
    try{
      return dtde.getCurrentDataFlavors();
    } catch (Throwable t){
      return null;
    }
  }

  public static java.awt.datatransfer.DataFlavor[] safeGetCurrentDataFlavors(java.awt.dnd.DropTargetDragEvent dtde){
    try{
      return dtde.getCurrentDataFlavors();
    } catch (Throwable t){
      return null;
    }
  }

  public static boolean safeIsDataFlavorSupported(java.awt.dnd.DropTargetDropEvent dtde, java.awt.datatransfer.DataFlavor flavor){
    try{
      boolean toReturn = dtde.isDataFlavorSupported(flavor);
      return toReturn;
    } catch (Throwable t){
      return false;
    }
  }

  public static boolean safeIsDataFlavorSupported(java.awt.datatransfer.Transferable transferable, java.awt.datatransfer.DataFlavor flavor){
    try{
      boolean toReturn = transferable.isDataFlavorSupported(flavor);
      return toReturn;
    } catch (Throwable t){
      return false;
    }
  }

  private static void loadResourcesPy() {
    resources = new Resources();
    AuthoringToolResources.initKeyCodesToStrings();

    AliceStyle.init();
  }

  // Define elements in "functions' tab", from: 'static void edu.cmu.cs.stage3.alice.authoringtool.py.StandardResources.questionStructure()'
  public static void setQuestionStructure (java.util.Vector questionStructure) {
    AuthoringToolResources.resources.questionStructure = questionStructure;
    }

  public static java.util.Vector getQuestionStructure (Class elementClass) {
    if (AuthoringToolResources.resources.questionStructure != null) {
      for (java.util.Iterator iter = AuthoringToolResources.resources.questionStructure.iterator(); iter.hasNext(); ) {
        Object o = iter.next();
        if ( o instanceof StringObjectPair ) {
          String className = ((StringObjectPair)o).getString();
          try {
            Class c = Class.forName( className );
            if ( c.isAssignableFrom( elementClass ) ) {
              // System.out.println("AuthoringToolResources.java: getQuestionStructure("+elementClass+"): "+className+"" );
              return (java.util.Vector)((StringObjectPair)o).getObject();
              }
          } catch (java.lang.ClassNotFoundException e) {
            AuthoringTool.getInstance().showErrorDialog("Can't find class " + className, e);
          }
        } else {
          AuthoringTool.getInstance().showErrorDialog("Unexpected object found in questionStructure: " + o, null);
          }
        }
      }
    return null;
    }

  public static void setDefaultPropertyValuesStructure( java.util.Vector defaultPropertyValuesStructure ) {
    AuthoringToolResources.resources.defaultPropertyValuesStructure = defaultPropertyValuesStructure;
  }

  public static java.util.Vector getDefaultPropertyValues( Class elementClass, String propertyName ) {
    if ( AuthoringToolResources.resources.defaultPropertyValuesStructure != null ) {
      for( java.util.Iterator iter = AuthoringToolResources.resources.defaultPropertyValuesStructure.iterator(); iter.hasNext(); ) {
        StringObjectPair classChunk = (StringObjectPair)iter.next();
        String className = classChunk.getString();
        try {
          Class c = Class.forName( className );
          if ( c.isAssignableFrom( elementClass ) ) {
            java.util.Vector properties = (java.util.Vector)classChunk.getObject();
            for( java.util.Iterator jter = properties.iterator(); jter.hasNext(); ) {
              StringObjectPair propertyChunk = (StringObjectPair)jter.next();
              if ( propertyName.equals( propertyChunk.getString() ) ) {
                return (java.util.Vector)propertyChunk.getObject();
              }
            }
          }
        } catch( java.lang.ClassNotFoundException e ) {
          AuthoringTool.getInstance().showErrorDialog( "Can't find class " + className, e );
        }
      }
    }

    return null;
  }

  public static void putName( Object key, String prettyName ) {
    AuthoringToolResources.resources.nameMap.put( key, prettyName );
  }

  public static String getName( Object key ) {
    return (String)AuthoringToolResources.resources.nameMap.get( key );
  }

  public static boolean nameMapContainsKey( Object key ) {
    return AuthoringToolResources.resources.nameMap.containsKey( key );
  }

  public static void putHTMLName( Object key, String prettyName ) {
    AuthoringToolResources.resources.htmlNameMap.put( key, prettyName );
  }

  public static String getHTMLName( Object key ) {
    return (String)AuthoringToolResources.resources.htmlNameMap.get( key );
  }

  public static void putFormat( Object key, String formatString ) {
    AuthoringToolResources.resources.formatMap.put( key, formatString );
  }

  public static String getFormat( Object key ) {
    return (String)AuthoringToolResources.resources.formatMap.get( key );
  }

  public static String getPlainFormat( Object key ) {
    String format = (String)AuthoringToolResources.resources.formatMap.get( key );
    StringBuffer sb = new StringBuffer();
    edu.cmu.cs.stage3.alice.authoringtool.util.FormatTokenizer tokenizer = new edu.cmu.cs.stage3.alice.authoringtool.util.FormatTokenizer( format );
    while( tokenizer.hasMoreTokens() ) {
      String token = tokenizer.nextToken();
      if ( (! token.startsWith( "<<" )) || token.startsWith( "<<<" ) ) {
        while( token.indexOf( "&lt;" ) > -1 ) {
          token = new StringBuffer( token ).replace( token.indexOf( "&lt;" ), token.indexOf( "&lt;" ) + 4, "<" ).toString();
        }
        sb.append( token );
      }
    }
    return sb.toString();
  }

  public static boolean formatMapContainsKey( Object key ) {
    return AuthoringToolResources.resources.formatMap.containsKey( key );
  }

  public static boolean shouldGUIOmitPropertyName( edu.cmu.cs.stage3.alice.core.Property property ) {
    return true;
  }

  //get repr in the context of a property
  public static String getReprForValue( Object value, edu.cmu.cs.stage3.alice.core.Property property ) {
    return getReprForValue( value, property, null );
  }

  public static String getReprForValue( Object value, edu.cmu.cs.stage3.alice.core.Property property, Object extraContextInfo ) {
    Class elementClass = property.getOwner().getClass();
    String propertyName = property.getName();
    if ( (property.getOwner() instanceof edu.cmu.cs.stage3.alice.core.response.PropertyAnimation) && property.getName().equals( "value" ) ) {
      edu.cmu.cs.stage3.alice.core.response.PropertyAnimation propertyAnimation = (edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)property.getOwner();
      Object e = propertyAnimation.element.get();
      if ( e instanceof edu.cmu.cs.stage3.alice.core.Expression ) {
        elementClass = ((edu.cmu.cs.stage3.alice.core.Expression)e).getValueClass();
      } else {
        Object elementValue = propertyAnimation.element.getElementValue();
        if ( elementValue != null ) {
          elementClass = elementValue.getClass();
        } else {
          elementClass = null;
        }
      }
      propertyName = propertyAnimation.propertyName.getStringValue();
    } else if ( (property.getOwner() instanceof edu.cmu.cs.stage3.alice.core.question.userdefined.PropertyAssignment) && property.getName().equals( "value" ) ) {
      edu.cmu.cs.stage3.alice.core.question.userdefined.PropertyAssignment propertyAssignment = (edu.cmu.cs.stage3.alice.core.question.userdefined.PropertyAssignment)property.getOwner();
      elementClass = propertyAssignment.element.getElementValue().getClass();
      propertyName = propertyAssignment.propertyName.getStringValue();
    }
    return getReprForValue( value, elementClass, propertyName, extraContextInfo );
  }
  public static String getReprForValue( Object value, Class elementClass, String propertyName, Object extraContextInfo ) {
    boolean verbose = false;
    Class valueClass = null;
    try {
      valueClass = edu.cmu.cs.stage3.alice.core.Element.getValueClassForPropertyNamed( elementClass, propertyName );
    } catch( Exception e ) { // a bit hackish
      valueClass = Object.class;
    }
    if ( valueClass == null ) { // another hack
      valueClass = Object.class;
    }
    if ( (elementClass == null) || (propertyName == null) ) {
      return getReprForValue( value );
    }

    if ( (edu.cmu.cs.stage3.alice.core.response.CallToUserDefinedResponse.class.isAssignableFrom( elementClass ) && propertyName.equals( "userDefinedResponse" )) ||
        (edu.cmu.cs.stage3.alice.core.question.userdefined.CallToUserDefinedQuestion.class.isAssignableFrom( elementClass ) && propertyName.equals( "userDefinedQuestion" )) )
    {
      verbose = true;
    }
    if ( (value instanceof edu.cmu.cs.stage3.alice.core.Variable) && (((edu.cmu.cs.stage3.alice.core.Variable)value).getParent() instanceof edu.cmu.cs.stage3.alice.core.Sandbox) ) {
      verbose = true;
    }

    try {
      while( edu.cmu.cs.stage3.alice.core.Element.class.isAssignableFrom( elementClass ) ) {

        String userRepr = null;
        if ( extraContextInfo instanceof edu.cmu.cs.stage3.alice.core.property.DictionaryProperty ) { // if there is extra info stored in the element's data property
          edu.cmu.cs.stage3.alice.core.property.DictionaryProperty data = (edu.cmu.cs.stage3.alice.core.property.DictionaryProperty)extraContextInfo;
          if ( data.getName().equals( "data" ) ) {  // sanity check
            Object repr = data.get( "edu.cmu.cs.stage3.alice.authoringtool.userRepr." + propertyName );
            if ( repr != null ) {
              if ( repr instanceof String ) {
                if ( Number.class.isAssignableFrom( valueClass ) && (value instanceof Double) ) { // if it's a number, check to make sure the string is still valid
                  Double d = AuthoringToolResources.parseDouble( (String)repr );
                  if ( (d != null) && d.equals( value ) ) {
                    userRepr = (String)repr;
                  } else {
                    data.remove( "edu.cmu.cs.stage3.alice.authoringtool.userRepr." + propertyName );
                  }
                } else {
                  userRepr = (String)repr;
                }
              }
            }
          }
        }

        String reprString = null;

        if ( reprString != null ) {

          while( reprString.indexOf( "<value>" ) > -1 ) {
            String valueString = (userRepr != null) ? userRepr : getReprForValue( value );
            StringBuffer sb = new StringBuffer( reprString );
            sb.replace( reprString.indexOf( "<value>" ), reprString.indexOf( "<value>" ) + "<value>".length(), valueString );
            reprString = sb.toString();
          }
          while( (reprString.indexOf( "<percentValue>" ) > -1) && (value instanceof Double) ) {
            double v = ((Double)value).doubleValue() * 100.0;
            String valueString = AuthoringToolResources.resources.decimalFormatter.format( v ) + "%";
            StringBuffer sb = new StringBuffer( reprString );
            sb.replace( reprString.indexOf( "<percentValue>" ), reprString.indexOf( "<percentValue>" ) + "<percentValue>".length(), valueString );
            reprString = sb.toString();
          }
          while( (reprString.indexOf( "<keyCodeValue>" ) > -1) && (value instanceof Integer) ) {
            String valueString = java.awt.event.KeyEvent.getKeyText( ((Integer)value).intValue() );
            StringBuffer sb = new StringBuffer( reprString );
            sb.replace( reprString.indexOf( "<keyCodeValue>" ), reprString.indexOf( "<keyCodeValue>" ) + "<keyCodeValue>".length(), valueString );
            reprString = sb.toString();
          }

          return reprString;
        }

        elementClass = elementClass.getSuperclass();
      }
    } catch( Throwable t ) {
      AuthoringTool.getInstance().showErrorDialog( "Error finding repr for " + value, t );
    }
    return getReprForValue( value, verbose );
  }


  public static String getReprForValue( Object value ) {
    return getReprForValue( value, false );
  }

  protected static String stripUnnamedsFromName(Object value){
    String toStrip = new String(value.toString());
    String toReturn = "";
    String toMatch = "__Unnamed";
    boolean notDone = true;
    while (notDone){
      int nextIndex = toStrip.indexOf(toMatch);
      if (nextIndex >= 0){
        String toAdd = toStrip.substring(0, nextIndex);
        if (toAdd != null){
          toReturn += toAdd;
        }
        String newToStrip = toStrip.substring(nextIndex, toStrip.length());
        if (newToStrip != null){
          toStrip = newToStrip;
        }
        else {
          notDone = false;
          break;
        }
        nextIndex = toStrip.indexOf(".");
        if (nextIndex >= 0){
          newToStrip = toStrip.substring(nextIndex+1, toStrip.length());
          if (newToStrip != null){
            toStrip = newToStrip;
          }
          else {
            notDone = false;
            break;
          }
        }else {
          notDone = false;
          break;
        }
      }
      else {
        toReturn += toStrip;
        notDone = false;
        break;
      }
    }
    return toStrip;
  }

  public static String getReprForValue( Object value, boolean verbose ) {
    if ( nameMapContainsKey( value ) ) {
      value = getName( value );
    }
    if ( formatMapContainsKey( value ) ) {
      value = getPlainFormat( value );
    }
    if ( value instanceof Class ) {
      value = ((Class)value).getName();
      if ( nameMapContainsKey( value ) ) {
        value = getName( value );
      }
    }
    if ( value instanceof Enumerable ) {
      value = ((Enumerable)value).getRepr();
    }
    if ( value instanceof edu.cmu.cs.stage3.alice.core.question.PropertyValue ) {
      String propertyName = ((edu.cmu.cs.stage3.alice.core.question.PropertyValue)value).propertyName.getStringValue();
      edu.cmu.cs.stage3.alice.core.Element element = (edu.cmu.cs.stage3.alice.core.Element)((edu.cmu.cs.stage3.alice.core.question.PropertyValue)value).element.get();
      Class valueClass = element.getClass();
      if ( element instanceof edu.cmu.cs.stage3.alice.core.Expression ) {
        valueClass = ((edu.cmu.cs.stage3.alice.core.Expression)element).getValueClass();
      }
      try {
        Class declaringClass = valueClass.getField( propertyName ).getDeclaringClass();
        if ( declaringClass != null ) {
          String key = declaringClass.getName() + "." + propertyName;
          if ( nameMapContainsKey( key ) ) {
            propertyName = getName( key );
          }
        }
      } catch( NoSuchFieldException e ) {
        AuthoringTool.getInstance().showErrorDialog( "Error representing PropertyValue: can't find " + propertyName + " on " + valueClass, e );
      }

      value = getReprForValue( element, false ) + "." + propertyName;
    }
    if ( (value instanceof edu.cmu.cs.stage3.alice.core.Question) && formatMapContainsKey( value.getClass() ) ) {
      String questionRepr = "";
      edu.cmu.cs.stage3.alice.core.Question question = (edu.cmu.cs.stage3.alice.core.Question)value;
      String format = getFormat( value.getClass() );
      edu.cmu.cs.stage3.alice.authoringtool.util.FormatTokenizer formatTokenizer = new edu.cmu.cs.stage3.alice.authoringtool.util.FormatTokenizer( format );
      //      int i = 0;
      while( formatTokenizer.hasMoreTokens() ) {
        String token = formatTokenizer.nextToken();
        if ( token.startsWith( "<" ) && token.endsWith( ">" ) ) {
          edu.cmu.cs.stage3.alice.core.Property property = question.getPropertyNamed( token.substring( token.lastIndexOf( "<" ) + 1, token.indexOf( ">" ) ) );
          if ( property != null ) {
            questionRepr += getReprForValue( property.get(), property );
          }
        } else {
          while( token.indexOf( "&lt;" ) > -1 ) {
            token = new StringBuffer( token ).replace( token.indexOf( "&lt;" ), token.indexOf( "&lt;" ) + 4, "<" ).toString();
          }
          questionRepr += token;
        }
      }

      if ( questionRepr.length() > 0 ) {
        value = questionRepr;
      }
    }
    if ( value instanceof edu.cmu.cs.stage3.alice.core.Element ) {
      if ( verbose ) {
        edu.cmu.cs.stage3.alice.core.Element ancestor = ((edu.cmu.cs.stage3.alice.core.Element)value).getSandbox();
        if ( ancestor != null ) {
          ancestor = ancestor.getParent();
        }
        value = ((edu.cmu.cs.stage3.alice.core.Element)value).getKey( ancestor );
        value = stripUnnamedsFromName(value);
      } else {
        value = ((edu.cmu.cs.stage3.alice.core.Element)value).name.getStringValue();
      }
    }
    if ( value instanceof Number ) {
      double d = ((Number)value).doubleValue();
      value = AuthoringToolResources.resources.decimalFormatter.format( d );
    }
    if ( value instanceof edu.cmu.cs.stage3.alice.core.Property ) {
      String simpleName = ((edu.cmu.cs.stage3.alice.core.Property)value).getName();
      if ( ((edu.cmu.cs.stage3.alice.core.Property)value).getDeclaredClass() != null ) {
        String key = ((edu.cmu.cs.stage3.alice.core.Property)value).getDeclaredClass().getName() + "." + ((edu.cmu.cs.stage3.alice.core.Property)value).getName();
        if ( nameMapContainsKey( key ) ) {
          simpleName = getName( key );
        } else {
          simpleName = ((edu.cmu.cs.stage3.alice.core.Property)value).getName();
        }
      }

      if ( ((edu.cmu.cs.stage3.alice.core.Property)value).getOwner() instanceof edu.cmu.cs.stage3.alice.core.Variable ) {
        value = getReprForValue( ((edu.cmu.cs.stage3.alice.core.Property)value).getOwner(), verbose );
      } else if ( verbose && (((edu.cmu.cs.stage3.alice.core.Property)value).getOwner() != null) ) {
        value = getReprForValue( ((edu.cmu.cs.stage3.alice.core.Property)value).getOwner() ) + "." + simpleName;
      } else {
        value = simpleName;
      }
    }
    if ( value == null ) {
      value = "<None>";
    }

    return value.toString();
  }

  public static String getFormattedReprForValue( Object value, StringObjectPair[] knownPropertyValues ) {
    String format = (String)AuthoringToolResources.resources.formatMap.get( value );
    StringBuffer sb = new StringBuffer();
    edu.cmu.cs.stage3.alice.authoringtool.util.FormatTokenizer tokenizer = new edu.cmu.cs.stage3.alice.authoringtool.util.FormatTokenizer( format );
    while( tokenizer.hasMoreTokens() ) {
      String token = tokenizer.nextToken();
      if ( token.startsWith( "<<<" ) && token.endsWith( ">>>" ) ) {
        String propertyName = token.substring( token.lastIndexOf( "<" ) + 1, token.indexOf( ">" ) );
        //LOB for (StringObjectPair knownPropertyValue : knownPropertyValues)
	StringObjectPair [] knownPropertyValue = knownPropertyValues;
        int _tam = knownPropertyValue!=null ? knownPropertyValue.length : 0;
        for (int _i=0; _i<_tam; _i++) {
          if ( knownPropertyValue[_i].getString().equals( propertyName ) ) { //L knownPropertyValue.getString().equals( propertyName )
            sb.append( AuthoringToolResources.getReprForValue( knownPropertyValue[_i].getObject(), true ) ); //L knownPropertyValue.getObject()
            break;
          }
        } // for (int _i=0; _i<_tam; _i++)
      } else if ( token.startsWith( "<<" ) && token.endsWith( ">>" ) ) {
        // leave blank
      } else if ( token.startsWith( "<" ) && token.endsWith( ">" ) ) {
        String propertyName = token.substring( token.lastIndexOf( "<" ) + 1, token.indexOf( ">" ) );
        boolean appendedValue = false;
        //LOB for (StringObjectPair knownPropertyValue : knownPropertyValues)
	StringObjectPair [] knownPropertyValue = knownPropertyValues;
        int _tam = knownPropertyValue!=null ? knownPropertyValue.length : 0;
        for (int _i=0; _i<_tam; _i++) {
          if ( knownPropertyValue[_i].getString().equals( propertyName ) ) { //L knownPropertyValue.getString().equals( propertyName )
            sb.append( AuthoringToolResources.getReprForValue( knownPropertyValue[_i].getObject(), true ) ); //L knownPropertyValue.getObject()
            break;
          }
        } // for (int _i=0; _i<_tam; _i++)

        if ( ! appendedValue ) {
          sb.append( token );
        }
      } else {
        sb.append( token );
      }
    }
    return sb.toString();
  }

  public static String getNameInContext (edu.cmu.cs.stage3.alice.core.Element element, edu.cmu.cs.stage3.alice.core.Element context) {
    if ( element instanceof edu.cmu.cs.stage3.alice.core.Variable ) {
      if ( element.getParent() != null ) {
        edu.cmu.cs.stage3.alice.core.Element variableRoot = element.getParent();
        if ( (variableRoot instanceof edu.cmu.cs.stage3.alice.core.Response) && (context.isDescendantOf( variableRoot ) || (context == variableRoot)) ) {
          return element.name.getStringValue();
          }
        }
      }

    return getReprForValue( element, true );
    }

  public static String[] getDesiredProperties (Class elementClass) {
    java.util.LinkedList desired = new java.util.LinkedList();
    String format = AuthoringToolResources.getFormat( elementClass );
    edu.cmu.cs.stage3.alice.authoringtool.util.FormatTokenizer tokenizer = new edu.cmu.cs.stage3.alice.authoringtool.util.FormatTokenizer( format );
    while( tokenizer.hasMoreTokens() ) {
      String token = tokenizer.nextToken();
      if ( token.startsWith( "<<<" ) && token.endsWith( ">>>" ) ) {
        // skip this one
        // should be in knownPropertyValues
      } else if ( token.startsWith( "<<" ) && token.endsWith( ">>" ) ) {
        desired.add( token.substring( token.lastIndexOf( "<" ) + 1, token.indexOf( ">" ) ) );
      } else if ( token.startsWith( "<" ) && token.endsWith( ">" ) ) {
        desired.add( token.substring( token.lastIndexOf( "<" ) + 1, token.indexOf( ">" ) ) );
        }
      }

    return (String[])desired.toArray( new String[0] );
    }

  public static void putColor (String key, java.awt.Color color) {
    AuthoringToolResources.resources.colorMap.put( key, color );
    }

  public static java.awt.Color getColor (String key) {
    java.awt.Color toReturn = (java.awt.Color)AuthoringToolResources.resources.colorMap.get( key );
    return toReturn;
    }

  public static java.awt.Image getAliceSystemIconImage () {
    return getImageForString("aliceHead");
    }
  public static javax.swing.ImageIcon getAliceSystemIcon () {
    return getIconForString("aliceHead");
    }

  // Came from: edu.cmu.cs.stage3.alice.authoringtool.JAliceFrame -> AuthoringToolResources.getAliceSystemIconImage()
  public static java.awt.Image getImageForString (String s) {
    //System.out.println("\n\n\nAuthoringToolResources.java: getImageForString("+s+"): "+s.substring(0,9));
    //System.out.println("AuthoringToolResources.java: getImageForString("+s+")");
    //if (s.substring(0,9).equals("aliceHead")) try{String str=""; System.out.println(str.charAt(3));}catch(Exception e){e.printStackTrace();}

    if ( ! AuthoringToolResources.resources.stringImageMap.containsKey( s ) ) {
      java.net.URL resource = AuthoringToolResources.class.getResource( "images/" + s + ".gif" );
      if ( resource == null ) {
        resource = AuthoringToolResources.class.getResource( "images/" + s + ".png" );
        }
      if ( resource == null ) {
        resource = AuthoringToolResources.class.getResource( "images/" + s + ".jpg" );
        }
      if ( resource != null ) {
        java.awt.Image image = java.awt.Toolkit.getDefaultToolkit().getImage( resource );
        AuthoringToolResources.resources.stringImageMap.put( s, image );
      } else {
        return null;
        }
      }
    return (java.awt.Image)AuthoringToolResources.resources.stringImageMap.get( s );
    }

  public static javax.swing.ImageIcon getIconForString( String s ) {
    // System.out.println("AuthoringToolResources.java: getIconForString("+s+")");
    if ( ! AuthoringToolResources.resources.stringIconMap.containsKey( s ) ) {
      java.net.URL resource = AuthoringToolResources.class.getResource( "images/" + s + ".gif" );
      if ( resource == null ) {
        resource = AuthoringToolResources.class.getResource( "images/" + s + ".png" );
      }
      if ( resource == null ) {
        resource = AuthoringToolResources.class.getResource( "images/" + s + ".jpg" );
      }
      if ( resource != null ) {
        AuthoringToolResources.resources.stringIconMap.put( s, new javax.swing.ImageIcon( resource ) );
      } else {
        return null;
        }
      }
    return (javax.swing.ImageIcon)AuthoringToolResources.resources.stringIconMap.get( s );
    }

  static final javax.swing.ImageIcon modelIcon = getIconForString( "model" );
  static final javax.swing.ImageIcon subpartIcon = getIconForString( "subpart" );
  static final javax.swing.ImageIcon sceneIcon = getIconForString( "scene" );
  static final javax.swing.ImageIcon folderIcon = getIconForString( "folder" );
  static final javax.swing.ImageIcon defaultIcon = getIconForString( "default" );

  public static javax.swing.ImageIcon getIconForValue (Object value) {
    if ( value instanceof edu.cmu.cs.stage3.alice.core.Transformable ) {
      if ( ((edu.cmu.cs.stage3.alice.core.Transformable)value).getParent() instanceof edu.cmu.cs.stage3.alice.core.Transformable ) {
        return subpartIcon;
      } else {
        return modelIcon;
        }
    } else if ( value instanceof edu.cmu.cs.stage3.alice.core.World ) {
      return sceneIcon;
    } else if ( value instanceof java.awt.Image ) {
      return new javax.swing.ImageIcon( (java.awt.Image)value );
    } else if ( value instanceof String ) {
      return getIconForString( (String)value );
    } else {
      return defaultIcon;
      }
    }

  public static javax.swing.ImageIcon getDisabledIcon (javax.swing.ImageIcon inputIcon) {
    return getDisabledIcon( inputIcon, 70 );
    }

  public static javax.swing.ImageIcon getDisabledIcon (javax.swing.ImageIcon inputIcon, int percentGray) {
    javax.swing.ImageIcon disabledIcon = (javax.swing.ImageIcon)AuthoringToolResources.resources.disabledIconMap.get( inputIcon );

    if ( disabledIcon == null ) {
      javax.swing.GrayFilter filter = new javax.swing.GrayFilter( true, percentGray );
      java.awt.image.ImageProducer producer = new java.awt.image.FilteredImageSource( inputIcon.getImage().getSource(), filter );
      java.awt.Image grayImage = java.awt.Toolkit.getDefaultToolkit().createImage( producer );
      disabledIcon = new javax.swing.ImageIcon( grayImage );
      AuthoringToolResources.resources.disabledIconMap.put( inputIcon, disabledIcon );
      }
    return disabledIcon;
    }

  public static void openURL (String urlString) throws java.io.IOException {
    if ( (System.getProperty( "os.name" ) != null) && System.getProperty( "os.name" ).startsWith( "Windows" ) ) {
      String[] cmdarray = new String[3];
      cmdarray[0] = "rundll32";
      cmdarray[1] = "url.dll,FileProtocolHandler";
      cmdarray[2] = urlString;

      if ( urlString.indexOf( "&stacktrace" ) > -1 ) {
        try {
          java.io.File tempURL = java.io.File.createTempFile( "tempURLHolder", ".url" );
          tempURL = tempURL.getAbsoluteFile();
          tempURL.deleteOnExit();
          java.io.PrintWriter urlWriter = new java.io.PrintWriter( new java.io.BufferedWriter( new java.io.FileWriter( tempURL ) ) );
          urlWriter.println( "[InternetShortcut]" );
          urlWriter.println( "URL=" + urlString );
          urlWriter.flush();
          urlWriter.close();
          cmdarray[2] = tempURL.getAbsolutePath();
        } catch( Throwable t ) {
          cmdarray[2] = urlString.substring( 0, urlString.indexOf( "&stacktrace" ) );
          }
        }
      Runtime.getRuntime().exec( cmdarray );
    } else {
      // try netscape
      String[] cmd = new String[] { "netscape", urlString };
      Runtime.getRuntime().exec( cmd );
      }
    }

  public static Double parseDouble (String doubleString) {
    Double number = null;
    if ( doubleString.trim().equalsIgnoreCase( "infinity" ) ) {
      number = new Double( Double.POSITIVE_INFINITY );
    } else if ( doubleString.trim().equalsIgnoreCase( "-infinity" ) ) {
      number = new Double( Double.NEGATIVE_INFINITY );
    } else if ( doubleString.indexOf( '/' ) > -1 ) {
      if ( doubleString.lastIndexOf( '/' ) == doubleString.indexOf( '/' ) ) {
        String numeratorString = doubleString.substring( 0, doubleString.indexOf( '/' ) );
        String denominatorString = doubleString.substring( doubleString.indexOf( '/' ) + 1 );
        try {
          number = new Double( Double.parseDouble( numeratorString ) / Double.parseDouble( denominatorString ) );
        } catch( NumberFormatException e ) {}
      }
    } else {
      try {
        number = Double.valueOf( doubleString );
      } catch( NumberFormatException e ) {}
      }
    return number;
    }

  public static boolean isMethodHookedUp (edu.cmu.cs.stage3.alice.core.Response response, edu.cmu.cs.stage3.alice.core.World world) {
    return isMethodHookedUp( response, world, new java.util.Vector() );
    }

  private static boolean isMethodHookedUp (edu.cmu.cs.stage3.alice.core.Response response, edu.cmu.cs.stage3.alice.core.World world, java.util.Vector checkedMethods) {
    PropertyReference[] references = response.getRoot().getPropertyReferencesTo( response, HowMuch.INSTANCE_AND_ALL_DESCENDANTS, false, true );
    //LOB for (PropertyReference reference : references)
    PropertyReference [] reference = references;
    int _tam = reference!=null ? reference.length : 0;
    for (int _i=0; _i<_tam; _i++) {
      edu.cmu.cs.stage3.alice.core.Element referrer = reference[_i].getProperty().getOwner(); //L reference.getProperty().getOwner()
      if ( world.behaviors.contains( referrer ) ) {
        return true;
      } else if ( (referrer instanceof edu.cmu.cs.stage3.alice.core.Response) && (! checkedMethods.contains( referrer )) ) {
        checkedMethods.add( referrer );
        if ( isMethodHookedUp( (edu.cmu.cs.stage3.alice.core.Response)referrer, world, checkedMethods ) ) {
          return true;
        }
      }
    }

    return false;
  }

  public static edu.cmu.cs.stage3.alice.core.Response createUndoResponse( edu.cmu.cs.stage3.alice.core.Response response ) {
    edu.cmu.cs.stage3.alice.core.Response undoResponse = null;

    if ( response instanceof edu.cmu.cs.stage3.alice.core.response.ResizeAnimation ) {
      edu.cmu.cs.stage3.alice.core.response.ResizeAnimation resizeResponse = (edu.cmu.cs.stage3.alice.core.response.ResizeAnimation)response;
      edu.cmu.cs.stage3.alice.core.response.ResizeAnimation undoResizeResponse = new edu.cmu.cs.stage3.alice.core.response.ResizeAnimation();

      undoResizeResponse.amount.set( new Double( 1.0/resizeResponse.amount.doubleValue() ) );
      undoResizeResponse.asSeenBy.set( resizeResponse.asSeenBy.get() );
      undoResizeResponse.likeRubber.set( resizeResponse.likeRubber.get() );
      undoResizeResponse.subject.set( resizeResponse.subject.get() );

      undoResponse = undoResizeResponse;
    } else if ( response instanceof edu.cmu.cs.stage3.alice.core.response.TransformAnimation ) {
      undoResponse = new edu.cmu.cs.stage3.alice.core.response.PropertyAnimation();
      edu.cmu.cs.stage3.alice.core.Transformable transformable = (edu.cmu.cs.stage3.alice.core.Transformable)((edu.cmu.cs.stage3.alice.core.response.TransformAnimation)response).subject.getValue();
      ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)undoResponse).element.set( transformable );
      ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)undoResponse).howMuch.set( HowMuch.INSTANCE );
    } else if ( response instanceof edu.cmu.cs.stage3.alice.core.response.PropertyAnimation ) {
      undoResponse = new edu.cmu.cs.stage3.alice.core.response.PropertyAnimation();
      edu.cmu.cs.stage3.alice.core.Element element = ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)response).element.getElementValue();
      ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)undoResponse).element.set( element );
      ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)undoResponse).propertyName.set( ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)response).propertyName.get() );
      ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)undoResponse).value.set( element.getPropertyNamed( ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)response).propertyName.getStringValue() ).getValue() );
      ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)undoResponse).howMuch.set( ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)response).howMuch.get() );
    }

    if ( undoResponse != null ) {
      undoResponse.duration.set( response.duration.get() );
    } else {
      undoResponse = new edu.cmu.cs.stage3.alice.core.response.Wait();
      undoResponse.duration.set( new Double( 0.0 ) );
      AuthoringTool.getInstance().showErrorDialog( "Could not create undoResponse for " + response, null );
    }

    return undoResponse;
  }

  public static void addAffectedProperties( java.util.List affectedProperties, edu.cmu.cs.stage3.alice.core.Element element, String propertyName, HowMuch howMuch ) {
    edu.cmu.cs.stage3.alice.core.Property property = element.getPropertyNamed( propertyName );
    if ( property != null ) {
      affectedProperties.add( property );
    }
    if ( howMuch.getDescend() ) {
      for( int i = 0;i < element.getChildCount(); i++ ) {
        edu.cmu.cs.stage3.alice.core.Element child = element.getChildAt( i );
        if (howMuch.getRespectDescendant() ) {
          //respect descendant
        } else {
          addAffectedProperties( affectedProperties, child, propertyName, howMuch );
        }
      }
    }
  }

  /**
   * this method only handles some cases.  you cannot depend on it to return the correct Property array for all responses.
   */
  public static edu.cmu.cs.stage3.alice.core.Property[] getAffectedProperties( edu.cmu.cs.stage3.alice.core.Response response ) {
    edu.cmu.cs.stage3.alice.core.Property[] properties = null;

    if ( response instanceof edu.cmu.cs.stage3.alice.core.response.ResizeAnimation ) {
      java.util.Vector pVector = new java.util.Vector();
      properties = (edu.cmu.cs.stage3.alice.core.Property[])pVector.toArray( new edu.cmu.cs.stage3.alice.core.Property[0] );
    } else if ( response instanceof edu.cmu.cs.stage3.alice.core.response.PropertyAnimation ) {
      edu.cmu.cs.stage3.alice.core.Element element = ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)response).element.getElementValue();
      String propertyName = ((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)response).propertyName.getStringValue();
      HowMuch howMuch = (HowMuch)((edu.cmu.cs.stage3.alice.core.response.PropertyAnimation)response).howMuch.getValue();

      java.util.LinkedList propertyList = new java.util.LinkedList();
      addAffectedProperties( propertyList, element, propertyName, howMuch );
      properties = (edu.cmu.cs.stage3.alice.core.Property[])propertyList.toArray( new edu.cmu.cs.stage3.alice.core.Property[0] );
    }

    if ( properties == null ) {
      properties = new edu.cmu.cs.stage3.alice.core.Property[0];
    }

    return properties;
  }

  public static String getNameForNewChild( String baseName, edu.cmu.cs.stage3.alice.core.Element parent ) {
    String name = baseName;

    if ( (name == null) || (parent == null) ) {
      return name;
    }

    if ( (parent.getChildNamedIgnoreCase( name ) == null) && (parent.getChildNamedIgnoreCase( name + 1 ) == null) ) {
      return name;
    }

    if ( baseName.length() < 1 ) {
      baseName = "copy";
    }

    // take baseName, strip a number off the end if necessary, and use next available number after the stripped number
    int begin = baseName.length() - 1;
    int end = baseName.length();
    int endDigit = 2;
    while( begin >= 0 ) {
      try {
        endDigit = Integer.parseInt( baseName.substring( begin, end ) );
        name = baseName.substring( 0, begin );
        begin--;
      } catch( NumberFormatException e ) {
        break;
      }
    }
    baseName = name;
    for( int i = endDigit; i < Integer.MAX_VALUE; i++ ) {
      name = baseName + i;
      if ( parent.getChildNamedIgnoreCase( name ) == null ) {
        return name;
      }
    }

    throw new RuntimeException( "Unable to find a suitable new name; baseName = " + baseName + ", parent = " + parent );
  }

  public static void addElementToAppropriateProperty( edu.cmu.cs.stage3.alice.core.Element element, edu.cmu.cs.stage3.alice.core.Element parent ) {
    edu.cmu.cs.stage3.alice.core.property.ObjectArrayProperty oap = null;

    if ( element instanceof edu.cmu.cs.stage3.alice.core.Transformable ) {
      if ( parent instanceof edu.cmu.cs.stage3.alice.core.Transformable ) {
        oap = ((edu.cmu.cs.stage3.alice.core.Transformable)parent).parts;
      }
    } else if ( element instanceof edu.cmu.cs.stage3.alice.core.Response ) {
      if ( parent instanceof edu.cmu.cs.stage3.alice.core.Sandbox ) {
        oap = ((edu.cmu.cs.stage3.alice.core.Sandbox)parent).responses;
      }
    } else if ( element instanceof edu.cmu.cs.stage3.alice.core.Behavior ) {
      if ( parent instanceof edu.cmu.cs.stage3.alice.core.Sandbox ) {
        oap = ((edu.cmu.cs.stage3.alice.core.Sandbox)parent).behaviors;
      }
    } else if ( element instanceof edu.cmu.cs.stage3.alice.core.Variable ) {
      if ( parent instanceof edu.cmu.cs.stage3.alice.core.Sandbox ) {
        oap = ((edu.cmu.cs.stage3.alice.core.Sandbox)parent).variables;
      }
    } else if ( element instanceof edu.cmu.cs.stage3.alice.core.Question ) {
      if ( parent instanceof edu.cmu.cs.stage3.alice.core.Sandbox ) {
        oap = ((edu.cmu.cs.stage3.alice.core.Sandbox)parent).questions;
      }
    }

    if ( oap != null ) {
      if ( ! oap.contains( element ) ) {
        oap.add( element );
      }
    }
  }

  public static double getCurrentTime() {
    long timeMillis = System.currentTimeMillis() - startTime;
    return timeMillis/1000.0;
  }

  public static void findAssignables( Class baseClass, java.util.Set result, boolean includeInterfaces ) {
    if ( baseClass != null ) {
      if ( ! result.contains( baseClass ) ) {
        result.add( baseClass );

        if ( includeInterfaces ) {
          Class[] interfaces = baseClass.getInterfaces();
          //LOB for (Class interface1 : interfaces)
          Class [] interface1 = interfaces;
          int _tam = interface1!=null ? interface1.length : 0;
          for (int _i=0; _i<_tam; _i++) {
            findAssignables( interface1[_i], result, includeInterfaces ); //L interface1
          }
        }

        findAssignables( baseClass.getSuperclass(), result, includeInterfaces );
      }
    }
  }

  public static java.awt.datatransfer.DataFlavor getReferenceFlavorForClass( Class c ) {
      //LOB version using 'mimeType' to create 'java.awt.datatransfer.DataFlavor' produce error in Java 5, changed to 'Class'
      java.awt.datatransfer.DataFlavor dataFlavor = null;
       if ( ! AuthoringToolResources.resources.flavorMap.containsKey( c ) ) {
          String class_name = "";
      try {
        // System.out.println("AuthoringToolResources.java: inserido em flavorMap '"+class_name+"'");
        // AuthoringToolResources.resources.flavorMap.put(c, new java.awt.datatransfer.DataFlavor(java.awt.datatransfer.DataFlavor.javaJVMLocalObjectMimeType+"; class="+c.getName());
        class_name = c.getName(); // this.getClass().newInstance();
        // String str = java.awt.datatransfer.DataFlavor.javaJVMLocalObjectMimeType+"; class="+class_name;
        // dataFlavor = new java.awt.datatransfer.DataFlavor(str);
        // AuthoringToolResources.resources.flavorMap.put(c, new java.awt.datatransfer.DataFlavor(java.awt.datatransfer.DataFlavor.javaJVMLocalObjectMimeType+"; class="+c.getName()));
        try {
           dataFlavor = new java.awt.datatransfer.DataFlavor(c, class_name); //LOB avoid error of 'java.awt.datatransfer.DataFlavor'
           AuthoringToolResources.resources.flavorMap.put(c, dataFlavor);
        } catch (Exception e1) {
           System.err.println("Error: AuthoringToolResources.java: getReferenceFlavorForClass: "+e1.toString());
           // AuthoringToolResources.resources.flavorMap.put(c, dataFlavor);
           // return dataFlavor;
           }
        //LOB  catch( ClassNotFoundException e )
      } catch( Exception e ) {
        System.err.println("Error: src/edu/cmu/cs/stage3/alice/authoringtool/AuthoringToolResources.java: "+
                           "getReferenceFlavorForClass(Class): "+e.toString());
        AuthoringTool.getInstance().showErrorDialog( "Can't find class " + class_name, e );
        AuthoringToolResources.resources.flavorMap.put(c, null);
        }
      }
        // java.util.HashMap htmlNameMap = new java.util.HashMap();
        // nameMap:
        // - 0: Object
        // - 1: For
        // - 2: Number
        // - 3: Return
        // - 4: When the world starts
        // - 5: If/Else
        // - 6: true
        // - 7: List iterator
        // - 8: While
        // - 9: Print
        // - 10: While the world is running
        // - 11: Boolean
        // - 12: false
        // flavorMap
        // - 0: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.Property]
        //  - 1: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.Element]
        //  - 2: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.response.DoInOrder]
        //  - 3: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.Expression]
        //  - 4: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.Variable]
        //  - 5: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.authoringtool.datatransfer.CommonMathQuestionsTransferable]
        //  - 6: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.World]
        //  - 7: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.question.userdefined.CallToUserDefinedQuestion]
        //  - 8: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.response.UserDefinedResponse]
        //  - 9: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=java.lang.Object]
        //  - 10: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.response.CallToUserDefinedResponse]
        //  - 11: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.Code]
        //  - 12: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.Question]
        //  - 13: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.Behavior]
        //  - 14: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.Response]
        //  - 15: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.response.CompositeResponse]
        //  - 16: java.awt.datatransfer.DataFlavor[mimetype=application/x-java-jvm-local-objectref;representationclass=edu.cmu.cs.stage3.alice.core.Transformable]
        //- java.util.HashMap hashmap = AuthoringToolResources.resources.flavorMap; // nameMap;
        //- int tam = hashmap.size(); // AuthoringToolResources.resources
        //- System.err.println("AuthoringToolResources.java: #AuthoringToolResources.resources="+tam+": "+c.getName()+" nao contido");
        //- java.util.Set set= hashmap.keySet();
        //- java.util.Iterator iter = set.iterator();
        //- int i=0;
        //- while ( iter.hasNext() ) { System.out.println(" - "+i+": "+hashmap.get( iter.next() ) ); i++; }

    return (java.awt.datatransfer.DataFlavor)AuthoringToolResources.resources.flavorMap.get( c );
  } // static java.awt.datatransfer.DataFlavor getReferenceFlavorForClass(Class c)

  public static Object getDefaultValueForClass( Class cls ) {
    if ( cls == Boolean.class ) {
      return Boolean.TRUE;
    } else if ( cls == Number.class ) {
      return new Double( 1 );
    } else if ( cls == String.class ) {
      return new String(I18n.getString("defaultString"));
    } else if ( cls == java.awt.Color.class ) {
      return java.awt.Color.white;
    } else if ( Enumerable.class.isAssignableFrom( cls ) ) {
      Enumerable[] items = Enumerable.getItems( cls );
      if ( items.length > 0 ) {
        return items[ 0 ];
      } else {
        return null;
      }
    } else if ( cls == edu.cmu.cs.stage3.alice.core.ReferenceFrame.class ) {
      return AuthoringTool.getInstance().getWorld();
    } else {
      return null;
    }
  }

  public static void garbageCollectIfPossible( PropertyReference[] references ) {
    //LOB for (PropertyReference reference : references)
    int t_tam = references!=null ? references.length : 0;
    for (int i_i=0; i_i<t_tam; i_i++) {
      edu.cmu.cs.stage3.alice.core.Element element = references[i_i].getProperty().getOwner(); //L reference.getProperty().getOwner()
      // if ( element instanceof edu.cmu.cs.stage3.alice.core.response.CallToUserDefinedResponse ) {
      PropertyReference[] metaReferences = element.getRoot().getPropertyReferencesTo( element, HowMuch.INSTANCE_AND_ALL_DESCENDANTS, false, true );
      if ( metaReferences.length == 0 ) {
        element.getParent().removeChild( element );
      }
      // }
    }
  }

  private static void initKeyCodesToStrings() {
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_0 ), "0" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_1 ), "1" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_2 ), "2" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_3 ), "3" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_4 ), "4" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_5 ), "5" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_6 ), "6" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_7 ), "7" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_8 ), "8" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_9 ), "9" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_A ), "A" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_B ), "B" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_C ), "C" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_D ), "D" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_E ), "E" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_F ), "F" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_G ), "G" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_H ), "H" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_I ), "I" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_J ), "J" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_K ), "K" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_L ), "L" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_M ), "M" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_N ), "N" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_O ), "O" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_P ), "P" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_Q ), "Q" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_R ), "R" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_S ), "S" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_T ), "T" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_U ), "U" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_V ), "V" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_W ), "W" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_X ), "X" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_Y ), "Y" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_Z ), "Z" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_ENTER ), "enter" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_SPACE ), "space" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_UP ), "upArrow" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_DOWN ), "downArrow" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_LEFT ), "leftArrow" );
    AuthoringToolResources.resources.keyCodesToStrings.put( new Integer( java.awt.event.KeyEvent.VK_RIGHT ), "rightArrow" );
  }

  /////////////////////////////
  // HACK code for stencils
  /////////////////////////////

  public static String getPrefix (String token) {
    if ( (token.indexOf( "<" ) > -1) && (token.indexOf( ">" ) > token.indexOf( "<" )) ) {
      return token.substring( 0, token.indexOf( "<" ) );
    } else {
      return token;
      }
    }

  public static String getSpecifier (String token) {
    if ( (token.indexOf( "<" ) > -1) && (token.indexOf( ">" ) > token.indexOf( "<" )) ) {
      return token.substring( token.indexOf( "<" ) + 1, token.indexOf( ">" ) );
    } else {
      return null;
      }
    }

  public static java.awt.Component findElementDnDPanel (java.awt.Container root, final edu.cmu.cs.stage3.alice.core.Element element) {
    Criterion criterion = new Criterion() {
      public boolean accept( Object o ) {
        if ( o instanceof edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel ) {
          try {
            java.awt.datatransfer.Transferable transferable = ((edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel)o).getTransferable();
            if ( (transferable != null) && AuthoringToolResources.safeIsDataFlavorSupported(transferable, ElementReferenceTransferable.elementReferenceFlavor ) ) {
              edu.cmu.cs.stage3.alice.core.Element e = (edu.cmu.cs.stage3.alice.core.Element)transferable.getTransferData( ElementReferenceTransferable.elementReferenceFlavor );
              if ( element.equals( e ) ) {
                return true;
                }
              }
          } catch (Exception e) {
            AuthoringTool.getInstance().showErrorDialog( "Error finding ElementDnDPanel.", e );
            }
          }
        return false;
        }
      };
    java.awt.Component toReturn = findComponent( root, criterion );
    if (toReturn instanceof MainCompositeElementPanel){
      return ((MainCompositeElementPanel)toReturn).getWorkSpace();
      }
    else {
      return toReturn;
      }
    }

  public static java.awt.Component findPropertyDnDPanel (java.awt.Container root, final edu.cmu.cs.stage3.alice.core.Element element, final String propertyName) {
    Criterion criterion = new Criterion() {
      public boolean accept( Object o ) {
        if ( o instanceof edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel ) {
          try {
            java.awt.datatransfer.Transferable transferable = ((edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel)o).getTransferable();
            if ( (transferable != null) && AuthoringToolResources.safeIsDataFlavorSupported( transferable,  PropertyReferenceTransferable.propertyReferenceFlavor ) ) {
              edu.cmu.cs.stage3.alice.core.Property p = (edu.cmu.cs.stage3.alice.core.Property)transferable.getTransferData( PropertyReferenceTransferable.propertyReferenceFlavor );
              edu.cmu.cs.stage3.alice.core.Element e = p.getOwner();
              if ( element.equals( e ) && p.getName().equals( propertyName ) ) {
                return true;
                }
              }
          } catch( Exception e ) {
            AuthoringTool.getInstance().showErrorDialog( "Error finding PropertyDnDPanel.", e );
            }
          }
        return false;
        }
      };

    return findComponent( root, criterion );
  }

  public static java.awt.Component findUserDefinedResponseDnDPanel (java.awt.Container root, final edu.cmu.cs.stage3.alice.core.Response actualResponse) {
    Criterion criterion = new Criterion() {
      public boolean accept( Object o ) {
        if ( o instanceof edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel ) {
          try {
            java.awt.datatransfer.Transferable transferable = ((edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel)o).getTransferable();
            if ( (transferable != null) && AuthoringToolResources.safeIsDataFlavorSupported( transferable, CallToUserDefinedResponsePrototypeReferenceTransferable.callToUserDefinedResponsePrototypeReferenceFlavor ) ) {
              edu.cmu.cs.stage3.alice.authoringtool.util.CallToUserDefinedResponsePrototype p = (edu.cmu.cs.stage3.alice.authoringtool.util.CallToUserDefinedResponsePrototype)transferable.getTransferData( CallToUserDefinedResponsePrototypeReferenceTransferable.callToUserDefinedResponsePrototypeReferenceFlavor );
              if ( p.getActualResponse().equals( actualResponse ) ) {
                return true;
                }
              }
          } catch( Exception e ) {
            AuthoringTool.getInstance().showErrorDialog( "Error finding UserDefinedResponseDnDPanel.", e );
            }
          }
        return false;
        }
      };
    return findComponent( root, criterion );
    }

  public static java.awt.Component findUserDefinedQuestionDnDPanel (java.awt.Container root, final edu.cmu.cs.stage3.alice.core.Question actualQuestion) {
    Criterion criterion = new Criterion() {
      public boolean accept( Object o ) {
        if ( o instanceof edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel ) {
          try {
            java.awt.datatransfer.Transferable transferable = ((edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel)o).getTransferable();
            if ( (transferable != null) && AuthoringToolResources.safeIsDataFlavorSupported( transferable, CallToUserDefinedQuestionPrototypeReferenceTransferable.callToUserDefinedQuestionPrototypeReferenceFlavor ) ) {
              edu.cmu.cs.stage3.alice.authoringtool.util.CallToUserDefinedQuestionPrototype p = (edu.cmu.cs.stage3.alice.authoringtool.util.CallToUserDefinedQuestionPrototype)transferable.getTransferData( CallToUserDefinedQuestionPrototypeReferenceTransferable.callToUserDefinedQuestionPrototypeReferenceFlavor );
              if ( p.getActualQuestion().equals( actualQuestion ) ) {
                return true;
                }
              }
          } catch( Exception e ) {
            AuthoringTool.getInstance().showErrorDialog( "Error finding UserDefinedQuestionDnDPanel.", e );
            }
          }
        return false;
        }
      };
    return findComponent( root, criterion );
    }

  public static java.awt.Component findPrototypeDnDPanel (java.awt.Container root, final Class elementClass) {
    Criterion criterion = new Criterion() {
      public boolean accept( Object o ) {
        if ( o instanceof edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel ) {
          try {
            java.awt.datatransfer.Transferable transferable = ((edu.cmu.cs.stage3.alice.authoringtool.util.DnDGroupingPanel)o).getTransferable();
            if ( (transferable != null) && AuthoringToolResources.safeIsDataFlavorSupported( transferable, ElementPrototypeReferenceTransferable.elementPrototypeReferenceFlavor ) ) {
              edu.cmu.cs.stage3.alice.authoringtool.util.ElementPrototype p = (edu.cmu.cs.stage3.alice.authoringtool.util.ElementPrototype)transferable.getTransferData( ElementPrototypeReferenceTransferable.elementPrototypeReferenceFlavor );
              if ( p.getElementClass().equals( elementClass ) ) {
                return true;
                }
              }
          } catch( Exception e ) {
            AuthoringTool.getInstance().showErrorDialog( "Error finding PrototypeDnDPanel.", e );
            }
          }
        return false;
        }
      };
    return findComponent( root, criterion );
    }

  public static java.awt.Component findPropertyViewController (java.awt.Container root, final edu.cmu.cs.stage3.alice.core.Element element, final String propertyName) {
    Criterion criterion = new Criterion() {
      public boolean accept( Object o ) {
        if ( o instanceof PropertyViewController) {
          edu.cmu.cs.stage3.alice.core.Property p = ((PropertyViewController)o).getProperty();
          if ( p.getOwner().equals( element ) && p.getName().equals( propertyName ) ) {
            return true;
            }
          }
        else if ( o instanceof CollectionPropertyViewController) {
          edu.cmu.cs.stage3.alice.core.Property p = ((CollectionPropertyViewController)o).getProperty();
          if ( p.getOwner().equals( element ) && p.getName().equals( propertyName ) ) {
            return true;
            }
          }
        return false;
        }
      };
    return findComponent( root, criterion );
    }

  public static java.awt.Component findEditObjectButton (java.awt.Container root, final edu.cmu.cs.stage3.alice.core.Element element) {
    Criterion criterion = new Criterion() {
      public boolean accept( Object o ) {
        if ( o instanceof edu.cmu.cs.stage3.alice.authoringtool.util.EditObjectButton ) {
          if ( ((edu.cmu.cs.stage3.alice.authoringtool.util.EditObjectButton)o).getObject().equals( element ) ) {
            return true;
            }
          }
        return false;
        }
      };
    return findComponent( root, criterion );
    }

  public static java.awt.Component findComponent (java.awt.Container root, Criterion criterion) {
    // System.out.println("AuthoringToolResources.java: findComponent("+edu.cmu.cs.stage3.util.StrUtilities.getComponentName(root)+", "+edu.cmu.cs.stage3.util.StrUtilities.getComponentName(criterion));
    // try {String str=""; System.out.println(str.charAt(3));}catch(Exception e) {e.printStackTrace();}

    if ( criterion.accept( root ) ) {
      return root;
      }

    java.awt.Component[] children = root.getComponents();
    //LOB for (Component element : children)
    int t_tam = children!=null ? children.length : 0;
    for (int i_i=0; i_i<t_tam; i_i++) {
      if ( children[i_i] instanceof java.awt.Container ) { //L element instanceof java.awt.Container
        java.awt.Component result = findComponent( (java.awt.Container)children[i_i], criterion ); //L  (java.awt.Container)element, criterion
        if ( result != null ) {
          return result;
          }
        }
      }
    return null;
    }

  }
